Skip to content

Add VectorTilesRasterOverlay#1365

Merged
j9liu merged 37 commits into
mainfrom
vector-tiles-overlay
May 28, 2026
Merged

Add VectorTilesRasterOverlay#1365
j9liu merged 37 commits into
mainfrom
vector-tiles-overlay

Conversation

@azrogers

@azrogers azrogers commented May 11, 2026

Copy link
Copy Markdown
Contributor

This PR adds support for rendering vector tilesets as a raster overlay. It uses a rasterization approach similar to the existing GeoJsonDocumentRasterOverlay, but instead of working from a single document, it works from a 3D Tiles tileset.

Future work after this PR is merged

  • How do we handle styling here? A single default style for the entire tileset only gets us so far. In the GeoJsonDocumentRasterOverlay we got away with letting users customize the styles on elements directly in the document before the raster overlay was loaded, so users can accomplish any kind of metadata styling or other sort of styling they're looking for. But we'll need a different approach for a 3D Tiles tileset. Is it finally time to handle style expressions? (Support for 3D Tiles Styling language #1208)
  • The EXT_mesh_polygon extension (see Add EXT_mesh_polygon KhronosGroup/glTF#2570) will continue to evolve, possibly in ways that break the current implementation of this extension. We will need to keep up-to-date with the changes and implement them as necessary.
  • This implementation is just blindly grabbing all the geometry it can find in the tileset and trying to interpret it as vector data. We should implement 3DTILES_content_gltf_vector (Add 3DTILES_content_gltf_vector 3d-tiles#838) as it matures.
  • We are currently doing a relatively inefficient full selection of the vector tiles tileset. This has some drawbacks, listed in Kevin's comment below. A more intelligent selection algorithm that takes into account the previous selections we've done would be ideal.
  • At the moment, the only tilesets we are seeing are tilesets that are exclusively vector data. However, it's possible that we will eventually see tilesets that combine vector data with regular geometry. In these cases where a vector tiles overlay is draped over the same tileset, we should use a reference to that tileset instead of creating a separate instance.

@azrogers azrogers marked this pull request as draft May 11, 2026 16:43
@j9liu j9liu requested review from Copilot and kring and removed request for Copilot May 12, 2026 15:11
@j9liu

j9liu commented May 12, 2026

Copy link
Copy Markdown
Contributor

Hey @kring! Are you able to take a glance from an architectural level for this PR?

@kring

kring commented May 18, 2026

Copy link
Copy Markdown
Member

If I can try to summarize how this works...

Every time we need a raster image for a terrain tile, we call findAndLoadTiles. It returns a future that eventually resolves to the vector tiles that need to be rendered, once all such tiles have been completely loaded.

findAndLoadTiles does a full traversal of the vector tile tree from the root. If any selected tiles still need to be loaded, then it calls itself recursively after the future returned by the first invocation resolves.

The futures returned by findAndLoadTiles are resolved by the tick method. This is necessary because we don't currently have a future that is resolved when a tile finishes loading. (In the normal SSE-based selection, we essentially poll for completion instead.)

The tick method is called every frame. It loops over all tiles that have a load in flight, and for each that has completed, it loops over all the "requests" (one per raster tile that is loading) to see if that tile uses that now-completed tile. Once a raster tile has no vector tile loads remaining, the request's promise is resolved. That will trigger another findAndLoadTiles (a full traversal) to make sure that there aren't now new tiles that we need to wait for.

This is potentially a lot of traversals. For vector tilesets with a small number of tiles, it probably isn't too bad. But I think it'll get pretty expensive for bigger ones.

Another more subtle problem is that a single call to loadTileImage can, in a tileset that uses lots of external tilesets or implicit subtrees, trigger a significant amount of loading. This loading is required in order to render the tile, so that's fine. Except that this loading process, once set in motion, will continue to completion even if the viewer moved away and this raster tile isn't even needed anymore.

I don't have any easy solution to this. Probably the ideal approach is more polling-based and incremental. That is, perhaps tick could a) check which (relevant) raster tiles are still in flight and advanced them by loading additional vector tiles if necessary, and b) do incremental traversals starting from a known point instead of traversing the entire vector tile tree from the root each time. It's not simple, though. (A) works against our raster overlay system, unfortunately. There's no way to "complete" a raster image load other than by providing the final image or failing it forever.

So I'd say it's reasonable to move forward with the current approach, and just keep an eye on how much time we're spending in this process as users start to work with larger vector tilesets.

@kring kring left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some smaller comments below.

Comment thread Cesium3DTilesSelection/include/Cesium3DTilesSelection/RasterOverlayCollection.h Outdated
Comment thread CesiumRasterOverlays/include/CesiumRasterOverlays/ActivatedRasterOverlay.h Outdated
// part 1 - selecting from scratch
if (this->_pTilesetContentManager->getRootTile() == nullptr) {
return this->_pTilesetContentManager->getRootTileAvailableEvent()
.thenInWorkerThread([this,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two problems here:

  1. I think the root tile available event can resolve while the root tile is still nullptr, e.g., if there's an error. If it does, this will be an endless promise cycle.
  2. It's not valid to call loadTileImageFromTileset in a worker thread, because it accesses the TilesetContentManager.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the root tile is still nullptr by the time it gets to findAndLoadTiles, it will return an empty set of tiles and so return an empty image. I don't think there's a way for it to get stuck in a loop.

Comment thread CesiumVectorOverlays/include/CesiumVectorOverlays/VectorTilesRasterOverlay.h Outdated
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated
Comment thread CesiumVectorOverlays/include/CesiumVectorOverlays/VectorTilesRasterOverlay.h Outdated
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated
@j9liu j9liu added this to the June 2026 Release milestone May 19, 2026
@azrogers azrogers marked this pull request as ready for review May 22, 2026 19:05
@j9liu

j9liu commented May 26, 2026

Copy link
Copy Markdown
Contributor

@kring just optionally requesting a review if you want to take another look. I'm doing a pass myself anyways :)

@j9liu j9liu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @azrogers for the PR! I have some comments but hopefully nothing too big to address.

I didn't get to pore through VectorTilesRasterOverlay.cpp as much as I wanted, but hopefully that's okay given @kring's previous look at the file?

Comment thread CesiumVectorData/include/CesiumVectorData/VectorStyle.h Outdated
Comment on lines +211 to +214
* This may be `nullptr` if there is currently no root tile.
*/
Tile* getRootTile() noexcept;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a good idea to discourage consumers of cesium-native from using this... would @private work for our documentation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for updateTileContent - I think it's fine to leave it open.

Comment thread CesiumRasterOverlays/include/CesiumRasterOverlays/ActivatedRasterOverlay.h Outdated
*
* @param tile The tile to update.
*/
void updateTileContent(Tile& tile);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth marking @Private?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's perfectly reasonable that a cesium-native consumer might want to use loadTiles directly and would need a way to access and modify the tiles and to update the tile content. I think it's fine to leave public with the explanation that it does not normally need to be called.

Comment thread CHANGES.md
Comment thread CesiumVectorOverlays/include/CesiumVectorOverlays/VectorTilesRasterOverlay.h Outdated
Comment thread CesiumVectorData/src/VectorRasterizer.cpp
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated
Comment thread CesiumVectorOverlays/src/VectorTilesRasterOverlay.cpp Outdated

@j9liu j9liu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @azrogers! Looking good, just waiting on CI to finish before merge.

@j9liu j9liu merged commit 9288bc5 into main May 28, 2026
28 checks passed
@j9liu j9liu deleted the vector-tiles-overlay branch May 28, 2026 20:57
@j9liu j9liu mentioned this pull request Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants